import datetime
import os.path

import cv2
import numpy as np
from PIL.Image import Image
from skimage.metrics import structural_similarity as compare_ssim
import imutils

from Logger.LoggerBase import log


def assert_img(img_fact,img_expected):
    """
    使用ssim算法，比较2个图片的相似度，相似度低于给定的数值就报错
    """
    #平滑处理分支，可以减少部分线条识别错误问题
    img1=cv2.cvtColor(np.array(Image.open(img_expected)),cv2.COLOR_BGR2RGB)
    img2=cv2.cvtColor(np.array(Image.open(img_fact)),cv2.COLOR_BGR2RGB)
    assert img1.shape!=(),f"{img_expected}可能不存在"
    assert img2.shape!=(),f"截图内容为空导致错误！可能是预期截图区域未在主屏幕或窗口被最小化"
    #将形状变得一致，否则无法比较
    if img2.shape!=img1.shape:
        img2=cv2.resize(img1,img1.shape[:-1][::-1],interpolation=cv2.INTER_LINEAR)

    #添加log等级处理
    (score,diff)=compare_ssim(img1,img2,full=True,multichannel=True)
    diff=np.array(diff*255).astype("uint8")
    diff=cv2.blur(diff,(5,5))
    diff=cv2.blur(diff,(5,5))

    thresh=cv2.threshold(diff,60,255,cv2.THRESH_BINARY_INV)[1]
    cnts=cv2.findContours(thresh[:,:,0],cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
    cnts=cnts[1] if imutils.is_cv2() else cnts[0]
    cnts=[item for item in cnts if item.size>10]

    diff_img=cv2.drawContours(img2,cnts,-1,(0,0,255),1)
    img_path,img_expected_name=os.path.split(img_expected)
    diff_img_path=os.path.join(img_path,"diff.jpg")

    cv2.imencode(".jpg",diff_img)[1].tofile(diff_img_path)
    cv2.waitKey(0)
    log.info(f"{img_expected}与{img_fact}相似度{score:.2%}")
    return score * 100,diff_img_path

def assert_img_gray(img_fact,img_expected):
    """
    比较两张图片的灰度图相似度，并生成差异标注图像
    参数:
        img_fact (str): 实际图像文件路径
        img_expected (str): 预期图像文件路径
    返回:
        tuple: (相似度百分比, 差异图像保存路径)
    """
    # 读取实际图像和预期图像（BGR格式）
    img_f = cv2.imread(img_fact)  # 加载实际图像到内存
    img_e = cv2.imread(img_expected)  # 加载预期图像到内存

    # 将图像转换为灰度图（减少颜色干扰）
    img_f_gray = cv2.cvtColor(img_f, cv2.COLOR_BGR2GRAY)  # 实际图像灰度化
    img_e_gray = cv2.cvtColor(img_e, cv2.COLOR_BGR2GRAY)  # 预期图像灰度化

    # 计算结构相似性指数（SSIM）和差异图
    (score, diff) = compare_ssim(img_f_gray, img_e_gray, full=True, multichannel=True)  # SSIM算法比较相似度
    diff = np.array(diff * 255).astype("uint8")  # 将差异图转换为0-255范围的整数

    # 对差异图进行两次高斯模糊（减少噪声干扰）
    diff = cv2.blur(diff, (5, 5))  # 第一次5x5模糊
    diff = cv2.blur(diff, (5, 5))  # 第二次模糊增强平滑效果

    # 二值化处理差异图（突出显著差异区域）
    thresh = cv2.threshold(diff, 60, 255, cv2.THRESH_BINARY_INV)[1]  # 阈值60，反向二值化

    # 查找差异轮廓（仅保留外部轮廓）
    cnts = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)  # 轮廓检测
    cnts = cnts[1] if imutils.is_cv2() else cnts[0]  # 兼容OpenCV不同版本的返回值

    # 过滤小面积轮廓（避免微小差异干扰）
    cnts = [item for item in cnts if cv2.contourArea(item) > 10]  # 面积阈值10像素

    # 在预期图像上绘制红色差异轮廓（线宽1像素）
    diff_img = cv2.drawContours(img_e, cnts, -1, (0, 0, 255), 1)  # 红色轮廓标注差异

    # 保存差异图像到原图同级目录
    img_path, img_expected_name = os.path.split(img_expected)  # 拆分路径和文件名
    diff_img_path = os.path.join(img_path, "diff.jpg")  # 构建差异图保存路径
    cv2.imencode(".jpg", diff_img)[1].tofile(diff_img_path)  # 编码并保存为JPEG

    # 显示图像（等待用户按键关闭窗口）
    cv2.waitKey(0)  # 阻塞模式显示图像窗口

    # 记录相似度结果到日志（百分比格式）
    log.info(f"{img_expected}与{img_fact}相似度{score:.2%}")  # 例如：输出"相似度95.34%"

    # 返回相似度（百分比）和差异图路径
    return score * 100, diff_img_path  # 相似度转换为百分数


def classify_hist_with_solit(image1,image2):
    image1=cv2.imread(image1)
    image2=cv2.imread(image2)
    sub_image1=cv2.split(image1)
    sub_image2=cv2.split(image2)
    sub_data=0
    for im1,im2 in zip(sub_image1,sub_image2):
        sub_data+=calculate(im1,im2)
    sub_data=sub_data/3
    return sub_data

def calculate(image1,image2):
    hist1=cv2.calcHist([image1],[0],None,[256],[0.0,255.0])
    hist2=cv2.calcHist([image2],[0],None,[256],[0.0,255.0])
    degree=0
    for i in range(len(hist1)):
        if hist1[i]!=hist2[i]:
            degree=degree+(1-abs(hist1[i]-hist2[i])/max(hist1[i],hist2[i]))
        else:
            degree=degree+1
    degree=degree/len(hist1)
    return degree

